﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

using HadronData;

namespace Hadron
{
    class Hud
    {
        private Environment m_environment;
        private double m_dTime;
        private int m_nIntegrityWidth, m_nFuelWidth, m_nScore;
        private GameFont m_gameFontHud, m_gameFontTimer;

        public Hud(Environment p_environment)
        {
            m_environment = p_environment;
            m_nIntegrityWidth = m_nFuelWidth = m_nScore = 0;
            m_gameFontHud = new GameFont(AssetManager.Fonts.Hud);
            m_gameFontTimer = new GameFont(AssetManager.Fonts.Timer);
            m_gameFontTimer.Alignment = GameFontAlignment.Centre;
        }

        public void Update(GameTime p_gameTime)
        {
            m_dTime = p_gameTime.TotalGameTime.TotalSeconds;

            PlayerShip playerShip = m_environment.PlayerShip;

            int nIntegrityTarget = (int)(playerShip.Integrity * 2.0f);
            if (m_nIntegrityWidth < nIntegrityTarget)
                ++m_nIntegrityWidth;
            else if (m_nIntegrityWidth > nIntegrityTarget)
                    --m_nIntegrityWidth;

            int nFuelTarget = (int)(playerShip.Fuel * 2.0f);

            int nActualScore = m_environment.Context.Score;
            if (m_nScore < nActualScore)
            {
                m_nScore = Math.Min(nActualScore, m_nScore + 10);
            }
            else if (m_nScore > nActualScore)
            {
                m_nScore = Math.Max(nActualScore, m_nScore - 100);
            }

            m_nFuelWidth = nFuelTarget;
        }

        public void Draw(SpriteBatch p_spriteBatch)
        {
            GraphicsDevice graphicsDevice = p_spriteBatch.GraphicsDevice;

            PlayerShip playerShip = m_environment.PlayerShip;
            int nScreenwidth = graphicsDevice.PresentationParameters.BackBufferWidth;
            int nScreenHeight = graphicsDevice.PresentationParameters.BackBufferHeight;
            int nMeterOffset = 12;

            float fMeterGlow = (1.0f + (float) Math.Sin(m_dTime * MathHelper.TwoPi)) * 0.5f;

            p_spriteBatch.Begin();

            // background
            p_spriteBatch.Draw(AssetManager.Textures.HudBackground, new Vector2(0.0f, nScreenHeight - 80.0f), Color.White);

            m_gameFontHud.Alignment = GameFontAlignment.Centre;
            m_gameFontHud.Colour = Color.LightGray;

            // player ship integrity
            int nMeterIntegrityY = nScreenHeight - 67;

            Rectangle rectangleIntegritySrc = new Rectangle(0, 0, m_nIntegrityWidth, 20);
            Rectangle rectangleIntegrityDst = new Rectangle(nMeterOffset, nMeterIntegrityY, m_nIntegrityWidth, 20);
            p_spriteBatch.Draw(AssetManager.Textures.MeterIntegrity, rectangleIntegrityDst, rectangleIntegritySrc, Color.White);

            // blend in red integrity component
            if (playerShip.Integrity < 20.0f) 
                p_spriteBatch.Draw(AssetManager.Textures.MeterLow, rectangleIntegrityDst,
                    rectangleIntegritySrc, new Color(Color.White, fMeterGlow));

            m_gameFontHud.DrawString(p_spriteBatch, new Vector2(110.0f, nMeterIntegrityY + 1.0f), "INTEGRITY");

            // player ship fuel
            int nMeterFuelY = nScreenHeight - 32;

            Rectangle rectangleFuelSrc = new Rectangle(0, 0, m_nFuelWidth, 20);
            Rectangle rectangleFuelDst = new Rectangle(nMeterOffset, nMeterFuelY, m_nFuelWidth, 20);
            p_spriteBatch.Draw(AssetManager.Textures.MeterFuel, rectangleFuelDst, rectangleFuelSrc, Color.White);

            // blend in red fuel component
            if (playerShip.Fuel < 20.0f)
                p_spriteBatch.Draw(AssetManager.Textures.MeterLow, rectangleFuelDst,
                    rectangleFuelSrc, new Color(Color.White, fMeterGlow));

            m_gameFontHud.DrawString(p_spriteBatch, new Vector2(110.0f, nMeterFuelY + 1), "FUEL");

            // stats

            // score
            m_gameFontHud.Alignment = GameFontAlignment.Centre;
            Vector2 vecStats = new Vector2(nScreenwidth * 0.5f, nScreenHeight - 64.0f);
            m_gameFontHud.DrawString(p_spriteBatch, vecStats, m_nScore.ToString());

            // lives
            vecStats = new Vector2(nScreenwidth * 0.5f + 20.0f, nScreenHeight - 35.0f);
            m_gameFontHud.Alignment = GameFontAlignment.Right;
            m_gameFontHud.DrawString(p_spriteBatch, vecStats, m_environment.Context.Lives.ToString());

            // scientists
            vecStats = new Vector2(nScreenwidth - 10.0f, nScreenHeight - 72.0f);
            m_gameFontHud.Alignment = GameFontAlignment.Right;
            m_gameFontHud.DrawString(p_spriteBatch, vecStats, m_environment.PlayerShip.ScientistsRescued.ToString());

            // crates
            vecStats = new Vector2(nScreenwidth - 10.0f, nScreenHeight - 48.0f);
            m_gameFontHud.Alignment = GameFontAlignment.Right;
            m_gameFontHud.DrawString(p_spriteBatch, vecStats, m_environment.PlayerShip.CratesDelivered.ToString());

            // reactors
            vecStats = new Vector2(nScreenwidth - 10.0f, nScreenHeight - 25.0f);
            m_gameFontHud.Alignment = GameFontAlignment.Right;
            m_gameFontHud.DrawString(p_spriteBatch, vecStats, m_environment.PlayerShip.ReactorsDestroyed.ToString());

            // countdown
            if (m_environment.CountdownActive)
            {
                int nCountdown = (int)m_environment.Countdown;
                float fFraction = m_environment.Countdown % 1.0f;
                m_gameFontTimer.Colour = new Color(1.0f, fFraction, 0.0f);
                m_gameFontTimer.DrawString(p_spriteBatch, new Vector2(400.0f, 460.0f),
                    nCountdown.ToString());
            }

            p_spriteBatch.End();
        }

        public Environment Environment
        {
            get { return m_environment; }
            set { m_environment = value; }
        }
    }
}
